/*
 * Copyright (c) Huawei Device Co., Ltd. 2024. All rights reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "ef_ac_conditions.h"

#include "arf_manager.h"
#include "device_appid_ref_do.h"
#include "loghelper.h"

namespace OHOS {
namespace SE {
EfAcConditions::EfAcConditions(std::shared_ptr<AidRefDo> aidRefDo)
    : EfParser()
{
    aidRefDo_ = aidRefDo;
}

EfAcConditions::~EfAcConditions()
{
}

bool EfAcConditions::ParseAcConditionFileDataInner(const std::vector<uint8_t> &fileData)
{
    std::vector<uint8_t> deviceAppId;
    std::shared_ptr<DerParser> der = std::make_shared<DerParser>(fileData);
    std::shared_ptr<DeviceAppIdRefDo> deviceAppIdRefDo =
        std::make_shared<DeviceAppIdRefDo>(std::vector<uint8_t>(), true);

    if (der->IsParsingEnd()) {
        InfoLog("ac condition file data empty, deny access for all apps.");
        ArfManager::GetInstance().AddArfRule(aidRefDo_, deviceAppIdRefDo, false);
        return true;
    }

    while (!der->IsParsingEnd()) {
        if (der->GetTlvDataLength(ASN1_SEQUENCE) > 0) {
            std::vector<uint8_t> tempTlvData = der->GetTlvData();
            std::shared_ptr<DerParser> tempDer = std::make_shared<DerParser>(tempTlvData);

            if (tempTlvData[0] == ASN1_OCTET_STRING) {
                tempDer->GetTlvDataLength(ASN1_OCTET_STRING);
                deviceAppId = tempDer->GetTlvData();
                if (deviceAppId.size() != HASH_SHA1_LEN && deviceAppId.size() != HASH_SHA256_LEN
                    && deviceAppId.size() != 0) {
                    ErrorLog("Found invalid app id!");
                    return false;
                } else {
                    deviceAppIdRefDo = std::make_shared<DeviceAppIdRefDo>(deviceAppId, true);
                }
            } else if (tempTlvData[0] == ASN1_PADDING_BYTE) {
                ErrorLog("Invalid app id found!");
                return false;
            } else {
                InfoLog("No app id found in file data.");
                deviceAppIdRefDo = std::make_shared<DeviceAppIdRefDo>(std::vector<uint8_t>(), true);
            }
        }
        ArfManager::GetInstance().AddArfRule(aidRefDo_, deviceAppIdRefDo, true);
    }
    return true;
}

void EfAcConditions::ParseAcConditionFileDataByPath(const std::vector<uint8_t> &acConditionFilePath)
{
    InfoLog("Parsing AC CONDITION file by path.");
    uint16_t rspApdu = 0;
    if (!ReadFileByPath(acConditionFilePath, rspApdu)) {
        ErrorLog("fail to read ac condition file, rspApdu[%{public}x]", rspApdu);
        return;
    }
    data_ = ReadFileByDataSize(0, -1);
    if (!ParseAcConditionFileDataInner(data_)) {
        ErrorLog("fail to parse fail data.");
    }
}

void EfAcConditions::ParseAcConditionFileData(const std::vector<uint8_t> &fileData)
{
    InfoLog("Parsing AC CONDITION file data.");
    if (fileData.size() != 0) {
        data_ = fileData;
        if (!ParseAcConditionFileDataInner(data_)) {
            ErrorLog("fail to parse ac condition file data.");
        }
    } else {
        ErrorLog("invalid file data.");
    }
}

std::vector<uint8_t> EfAcConditions::GetData()
{
    return data_;
}

}  // namespace SE
}  // namespace OHOS
